3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xc/py/XenoUtil.py
3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
+4054a2fdkdATEnRw-U7AUlgu-6JiUA tools/xend/setup.py
+4054a301VEag2GwrBrFBna5U1BGlLA tools/xend/xend.py
40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/xend_utils.c
403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
xc.domain_destroy ( dom=id )
sys.exit()
- ports = xc.evtchn_open( dom2=id )
- if not ports:
+ cmsg = 'new_control_interface(dom='+str(id)+')'
+ xend_response = XenoUtil.xend_control_message(cmsg)
+ if not xend_response['success']:
print "Error creating initial event channel"
+ print "Error type: " + xend_response['error_type']
+ if xend_response['error_type'] == 'exception':
+ print "Exception type: " + xend_response['exception_type']
+ print "Exception value: " + xend_response['exception_value']
xc.domain_destroy ( dom=id )
sys.exit()
xc.domain_destroy ( dom=id )
sys.exit()
- return (id, 9600+ports['port1'])
+ return (id, xend_response['console_port'])
# end of make_domain()
def mkpidfile():
-all: ../lib/libxc.so.1.3.0 ../lib/xc.h
+all:
python setup.py build
install: all
/******************************************************************************
* Xc.c
*
- * Copyright (c) 2003, K A Fraser
+ * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
*/
#include <Python.h>
#include <xc.h>
-#if 1
-#define DPRINTF(_f, _a...) \
- fprintf(stderr, "%s:%s:%d:: " _f "\n" , \
- __FILE__ , __FUNCTION__ , __LINE__ , ## _a)
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
+static PyObject *xc_error, *zero;
typedef struct {
PyObject_HEAD;
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|is", kwd_list,
&mem_kb, &name) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, &dom)) < 0 )
- return PyLong_FromLong(ret);
+ return PyErr_SetFromErrno(xc_error);
return PyLong_FromUnsignedLongLong(dom);
}
XcObject *xc = (XcObject *)self;
u64 dom;
- int ret;
static char *kwd_list[] = { "dom", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &dom) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_domain_start(xc->xc_handle, dom);
+ if ( xc_domain_start(xc->xc_handle, dom) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_domain_stop(PyObject *self,
XcObject *xc = (XcObject *)self;
u64 dom;
- int ret;
static char *kwd_list[] = { "dom", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &dom) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_domain_stop(xc->xc_handle, dom);
+ if ( xc_domain_stop(xc->xc_handle, dom) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_domain_destroy(PyObject *self,
XcObject *xc = (XcObject *)self;
u64 dom;
- int force = 0, ret;
+ int force = 0;
static char *kwd_list[] = { "dom", "force", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L|i", kwd_list,
&dom, &force) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_domain_destroy(xc->xc_handle, dom, force);
+ if ( xc_domain_destroy(xc->xc_handle, dom, force) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_domain_pincpu(PyObject *self,
XcObject *xc = (XcObject *)self;
u64 dom;
- int cpu = -1, ret;
+ int cpu = -1;
static char *kwd_list[] = { "dom", "cpu", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L|i", kwd_list,
&dom, &cpu) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_domain_pincpu(xc->xc_handle, dom, cpu);
+ if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_domain_getinfo(PyObject *self,
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|Li", kwd_list,
&first_dom, &max_doms) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
- {
- DPRINTF("out of memory.");
- nr_doms = 0;
- }
- else
- {
- nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
- }
+ return PyErr_NoMemory();
+
+ nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
list = PyList_New(nr_doms);
for ( i = 0 ; i < nr_doms; i++ )
"name", info[i].name));
}
- if ( info != NULL )
- free(info);
+ free(info);
return list;
}
u64 dom;
char *state_file;
- int progress = 1, ret;
+ int progress = 1;
static char *kwd_list[] = { "dom", "state_file", "progress", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Ls|i", kwd_list,
&dom, &state_file, &progress) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_linux_save(xc->xc_handle, dom, state_file, progress);
+ if ( xc_linux_save(xc->xc_handle, dom, state_file, progress) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_linux_restore(PyObject *self,
XcObject *xc = (XcObject *)self;
char *state_file;
- int progress = 1, ret;
+ int progress = 1;
u64 dom;
static char *kwd_list[] = { "state_file", "progress", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwd_list,
&state_file, &progress) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_linux_restore(xc->xc_handle, state_file, progress, &dom);
- if ( ret < 0 )
- return PyLong_FromLong(ret);
+ if ( xc_linux_restore(xc->xc_handle, state_file, progress, &dom) != 0 )
+ return PyErr_SetFromErrno(xc_error);
return PyLong_FromUnsignedLongLong(dom);
}
u64 dom;
char *image, *ramdisk = NULL, *cmdline = "";
- int ret;
static char *kwd_list[] = { "dom", "image", "ramdisk", "cmdline", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Ls|ss", kwd_list,
&dom, &image, &ramdisk, &cmdline) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_linux_build(xc->xc_handle, dom, image, ramdisk, cmdline);
+ if ( xc_linux_build(xc->xc_handle, dom, image, ramdisk, cmdline) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_netbsd_build(PyObject *self,
u64 dom;
char *image, *ramdisk = NULL, *cmdline = "";
- int ret;
static char *kwd_list[] = { "dom", "image", "ramdisk", "cmdline", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Ls|ss", kwd_list,
&dom, &image, &ramdisk, &cmdline) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_netbsd_build(xc->xc_handle, dom, image, cmdline);
+ if ( xc_netbsd_build(xc->xc_handle, dom, image, cmdline) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_bvtsched_global_set(PyObject *self,
XcObject *xc = (XcObject *)self;
unsigned long ctx_allow;
- int ret;
static char *kwd_list[] = { "ctx_allow", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_bvtsched_global_set(xc->xc_handle, ctx_allow);
+ if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
u64 dom;
unsigned long mcuadv, warp, warpl, warpu;
- int ret;
static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
"warpu", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Lllll", kwd_list,
&dom, &mcuadv, &warp, &warpl, &warpu) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
- warp, warpl, warpu);
+ if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
+ warp, warpl, warpu) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_vif_scheduler_set(PyObject *self,
u64 dom;
unsigned int vif;
xc_vif_sched_params_t sched = { 0, 0 };
- int ret;
static char *kwd_list[] = { "dom", "vif", "credit_bytes",
"credit_usecs", NULL };
&dom, &vif,
&sched.credit_bytes,
&sched.credit_usec) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_vif_scheduler_set(xc->xc_handle, dom, vif, &sched);
+ if ( xc_vif_scheduler_set(xc->xc_handle, dom, vif, &sched) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_vif_scheduler_get(PyObject *self,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
- PyObject *dict;
u64 dom;
unsigned int vif;
xc_vif_sched_params_t sched;
- int ret;
static char *kwd_list[] = { "dom", "vif", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list,
&dom, &vif) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_vif_scheduler_get(xc->xc_handle, dom, vif, &sched);
+ if ( xc_vif_scheduler_get(xc->xc_handle, dom, vif, &sched) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- if ( ret < 0 )
- dict = Py_BuildValue("{}");
- else
- dict = Py_BuildValue("{s:l,s:l}",
- "credit_bytes", sched.credit_bytes,
- "credit_usecs", sched.credit_usec);
-
- return dict;
+ return Py_BuildValue("{s:l,s:l}",
+ "credit_bytes", sched.credit_bytes,
+ "credit_usecs", sched.credit_usec);
}
static PyObject *pyxc_vif_stats_get(PyObject *self,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
- PyObject *dict;
u64 dom;
unsigned int vif;
xc_vif_stats_t stats;
- int ret;
static char *kwd_list[] = { "dom", "vif", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list,
&dom, &vif) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_vif_stats_get(xc->xc_handle, dom, vif, &stats);
+ if ( xc_vif_stats_get(xc->xc_handle, dom, vif, &stats) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- if ( ret < 0 )
- dict = Py_BuildValue("{}");
- else
- dict = Py_BuildValue("{s:L,s:L,s:L,s:L}",
- "tx_bytes", stats.tx_bytes,
- "tx_packets", stats.tx_pkts,
- "rx_bytes", stats.rx_bytes,
- "rx_packets", stats.rx_pkts);
-
- return dict;
+ return Py_BuildValue("{s:L,s:L,s:L,s:L}",
+ "tx_bytes", stats.tx_bytes,
+ "tx_packets", stats.tx_pkts,
+ "rx_bytes", stats.rx_bytes,
+ "rx_packets", stats.rx_pkts);
}
static PyObject *pyxc_vbd_create(PyObject *self,
u64 dom;
unsigned int vbd;
- int writeable, ret;
+ int writeable;
static char *kwd_list[] = { "dom", "vbd", "writeable", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Lii", kwd_list,
&dom, &vbd, &writeable) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_vbd_create(xc->xc_handle, dom, vbd, writeable);
-
- return PyInt_FromLong(ret);
+ if ( xc_vbd_create(xc->xc_handle, dom, vbd, writeable) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_vbd_destroy(PyObject *self,
u64 dom;
unsigned int vbd;
- int ret;
static char *kwd_list[] = { "dom", "vbd", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list,
&dom, &vbd) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_vbd_destroy(xc->xc_handle, dom, vbd);
-
- return PyInt_FromLong(ret);
+ if ( xc_vbd_destroy(xc->xc_handle, dom, vbd) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_vbd_grow(PyObject *self,
u64 dom;
unsigned int vbd;
xc_vbdextent_t extent;
- int ret;
static char *kwd_list[] = { "dom", "vbd", "device",
"start_sector", "nr_sectors", NULL };
&extent.real_device,
&extent.start_sector,
&extent.nr_sectors) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_vbd_grow(xc->xc_handle, dom, vbd, &extent);
-
- return PyInt_FromLong(ret);
+ if ( xc_vbd_grow(xc->xc_handle, dom, vbd, &extent) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_vbd_shrink(PyObject *self,
u64 dom;
unsigned int vbd;
- int ret;
static char *kwd_list[] = { "dom", "vbd", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list,
&dom, &vbd) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_vbd_shrink(xc->xc_handle, dom, vbd);
-
- return PyInt_FromLong(ret);
+ if ( xc_vbd_shrink(xc->xc_handle, dom, vbd) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_vbd_setextents(PyObject *self,
u64 dom;
unsigned int vbd;
xc_vbdextent_t *extents = NULL;
- int ret, i, nr_extents;
+ int i, nr_extents;
static char *kwd_list[] = { "dom", "vbd", "extents", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "LiO", kwd_list,
&dom, &vbd, &list) )
- {
- DPRINTF("could not parse parameter list.");
- goto fail;
- }
+ return NULL;
- if ( (nr_extents = PyList_Size(list)) < 0 )
+ if ( !PyList_Check(list) )
{
- DPRINTF("parameter 'extents' is not a list.");
- goto fail;
+ PyErr_SetString(PyExc_TypeError, "parameter 'extents' is not a list");
+ return NULL;
}
- if ( nr_extents != 0 )
+ if ( (nr_extents = PyList_Size(list)) != 0 )
{
- extents = malloc(nr_extents * sizeof(xc_vbdextent_t));
- if ( extents == NULL )
- {
- DPRINTF("out of memory.");
- goto fail;
- }
+ if ( (extents = malloc(nr_extents * sizeof(xc_vbdextent_t))) == NULL )
+ return PyErr_NoMemory();
for ( i = 0; i < nr_extents; i++ )
{
dict = PyList_GetItem(list, i);
if ( !PyDict_Check(dict) )
{
- DPRINTF("extent %d -- extent is not a dictionary.", i);
+ PyErr_SetString(PyExc_TypeError, "extent is not a dictionary");
goto fail;
}
if ( (obj = PyDict_GetItemString(dict, "device")) == NULL )
{
- DPRINTF("extent %d -- 'device' is not in the dictionary.", i);
+ PyErr_SetString(PyExc_TypeError,
+ "'device' is not in the dictionary");
goto fail;
}
if ( PyInt_Check(obj) )
}
else
{
- DPRINTF("extent %d -- 'device' is not an int or long.", i);
+ PyErr_SetString(PyExc_TypeError,
+ "'device' is not an int or long");
goto fail;
}
if ( (obj = PyDict_GetItemString(dict, "start_sector")) == NULL )
{
- DPRINTF("extent %d -- 'start_sector' is not "
- "in the dictionary.", i);
+ PyErr_SetString(PyExc_TypeError,
+ "'start_sector' is not in the dictionary");
goto fail;
}
if ( PyInt_Check(obj) )
}
else
{
- DPRINTF("extent %d -- 'start_sector' is not "
- "an int or long.", i);
+ PyErr_SetString(PyExc_TypeError,
+ "'start_sector' is not an int or long");
goto fail;
}
if ( (obj = PyDict_GetItemString(dict, "nr_sectors")) == NULL )
{
- DPRINTF("extent %d -- 'nr_sectors' is not "
- "in the dictionary.", i);
+ PyErr_SetString(PyExc_TypeError,
+ "'nr_sectors' is not in the dictionary");
goto fail;
}
if ( PyInt_Check(obj) )
}
else
{
- DPRINTF("extent %d -- 'nr_sectors' is not "
- "an int or long.", i);
+ PyErr_SetString(PyExc_TypeError,
+ "'nr_sectors' is not an int or long");
goto fail;
}
}
}
- ret = xc_vbd_setextents(xc->xc_handle, dom, vbd, nr_extents, extents);
-
+ if ( xc_vbd_setextents(xc->xc_handle, dom, vbd, nr_extents, extents) != 0 )
+ {
+ PyErr_SetFromErrno(xc_error);
+ goto fail;
+ }
+
if ( extents != NULL )
free(extents);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
fail:
if ( extents != NULL )
u64 dom;
unsigned int vbd;
xc_vbdextent_t *extents;
- int i, nr_extents, max_extents;
+ int i, nr_extents;
static char *kwd_list[] = { "dom", "vbd", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list,
&dom, &vbd) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- extents = malloc(MAX_EXTENTS * sizeof(xc_vbdextent_t));
- if ( extents == NULL )
- {
- DPRINTF("out of memory.");
- max_extents = 0;
- }
- else
- {
- max_extents = MAX_EXTENTS;
- }
+ if ( (extents = malloc(MAX_EXTENTS * sizeof(xc_vbdextent_t))) == NULL )
+ return PyErr_NoMemory();
- nr_extents = xc_vbd_getextents(xc->xc_handle, dom, vbd, max_extents,
+ nr_extents = xc_vbd_getextents(xc->xc_handle, dom, vbd, MAX_EXTENTS,
extents, NULL);
- if ( nr_extents <= 0 )
+ if ( nr_extents < 0 )
{
- list = PyList_New(0);
+ free(extents);
+ return PyErr_SetFromErrno(xc_error);
}
- else
+
+ list = PyList_New(nr_extents);
+ for ( i = 0; i < nr_extents; i++ )
{
- list = PyList_New(nr_extents);
- for ( i = 0; i < nr_extents; i++ )
- {
- PyList_SetItem(
- list, i,
- Py_BuildValue("{s:i,s:L,s:L}",
- "device", extents[i].real_device,
- "start_sector", extents[i].start_sector,
- "nr_sectors", extents[i].nr_sectors));
- }
+ PyList_SetItem(
+ list, i,
+ Py_BuildValue("{s:i,s:L,s:L}",
+ "device", extents[i].real_device,
+ "start_sector", extents[i].start_sector,
+ "nr_sectors", extents[i].nr_sectors));
}
- if ( extents != NULL )
- free(extents);
+ free(extents);
return list;
}
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|Li", kwd_list,
&dom, &max_vbds) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- info = malloc(max_vbds * sizeof(xc_vbd_t));
- if ( info == NULL )
- {
- DPRINTF("out of memory.");
- nr_vbds = 0;
- }
- else
+ if ( (info = malloc(max_vbds * sizeof(xc_vbd_t))) == NULL )
+ return PyErr_NoMemory();
+
+ if ( (nr_vbds = xc_vbd_probe(xc->xc_handle, dom, max_vbds, info)) < 0 )
{
- nr_vbds = xc_vbd_probe(xc->xc_handle, dom, max_vbds, info);
+ free(info);
+ return PyErr_SetFromErrno(xc_error);
}
list = PyList_New(nr_vbds);
"nr_sectors", info[i].nr_sectors));
}
- if ( info != NULL )
- free(info);
+ free(info);
return list;
}
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
- PyObject *dict;
u64 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
- int port1, port2, ret;
+ int port1, port2;
static char *kwd_list[] = { "dom1", "dom2", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|LL", kwd_list,
&dom1, &dom2) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_evtchn_open(xc->xc_handle, dom1, dom2, &port1, &port2);
+ if ( xc_evtchn_open(xc->xc_handle, dom1, dom2, &port1, &port2) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- if ( ret < 0 )
- dict = Py_BuildValue("{}");
- else
- dict = Py_BuildValue("{s:i,s:i}",
- "port1", port1,
- "port2", port2);
-
- return dict;
+ return Py_BuildValue("{s:i,s:i}",
+ "port1", port1,
+ "port2", port2);
}
static PyObject *pyxc_evtchn_close(PyObject *self,
XcObject *xc = (XcObject *)self;
u64 dom = DOMID_SELF;
- int port, ret;
+ int port;
static char *kwd_list[] = { "port", "dom", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|L", kwd_list,
&port, &dom) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_evtchn_close(xc->xc_handle, dom, port);
+ if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_evtchn_send(PyObject *self,
{
XcObject *xc = (XcObject *)self;
- int port, ret;
+ int port;
static char *kwd_list[] = { "port", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
- ret = xc_evtchn_send(xc->xc_handle, port);
+ if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyInt_FromLong(ret);
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_evtchn_status(PyObject *self,
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|L", kwd_list,
&port1, &dom1) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
ret = xc_evtchn_status(xc->xc_handle, dom1, port1, &dom2, &port2, &status);
+ if ( ret != 0 )
+ return PyErr_SetFromErrno(xc_error);
- if ( ret < 0 )
+ switch ( status )
{
+ case EVTCHNSTAT_closed:
+ dict = Py_BuildValue("{s:s}",
+ "status", "closed");
+ break;
+ case EVTCHNSTAT_disconnected:
+ dict = Py_BuildValue("{s:s}",
+ "status", "disconnected");
+ break;
+ case EVTCHNSTAT_connected:
+ dict = Py_BuildValue("{s:s,s:L,s:i}",
+ "status", "connected",
+ "dom", dom2,
+ "port", port2);
+ break;
+ default:
dict = Py_BuildValue("{}");
- }
- else
- {
- switch ( status )
- {
- case EVTCHNSTAT_closed:
- dict = Py_BuildValue("{s:s}",
- "status", "closed");
- break;
- case EVTCHNSTAT_disconnected:
- dict = Py_BuildValue("{s:s}",
- "status", "disconnected");
- break;
- case EVTCHNSTAT_connected:
- dict = Py_BuildValue("{s:s,s:L,s:i}",
- "status", "connected",
- "dom", dom2,
- "port", port2);
- break;
- default:
- dict = Py_BuildValue("{}");
- break;
- }
+ break;
}
return dict;
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Liiii", kwd_list,
&dom, &bus, &dev, &func, &enable) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
ret = xc_physdev_pci_access_modify(
xc->xc_handle, dom, bus, dev, func, enable);
-
- return PyInt_FromLong(ret);
+ if ( ret != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
}
static PyObject *pyxc_readconsolering(PyObject *self,
static char *kwd_list[] = { "clear", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
- {
- DPRINTF("could not parse parameter list.");
return NULL;
- }
ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
+ if ( ret < 0 )
+ return PyErr_SetFromErrno(xc_error);
- return PyString_FromStringAndSize(str, (ret < 0) ? 0 : ret);
+ return PyString_FromStringAndSize(str, ret);
}
static PyObject *pyxc_physinfo(PyObject *self,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
- PyObject *ret_obj;
- int xc_ret;
xc_physinfo_t info;
- if ( (xc_ret = xc_physinfo(xc->xc_handle, &info)) == 0 )
- {
- ret_obj = Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
- "ht_per_core", info.ht_per_core,
- "cores", info.cores,
- "total_pages", info.total_pages,
- "free_pages", info.free_pages,
- "cpu_khz", info.cpu_khz);
- }
- else
- {
- Py_INCREF(Py_None);
- ret_obj = Py_None;
- }
-
- return ret_obj;
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( xc_physinfo(xc->xc_handle, &info) != 0 )
+ return PyErr_SetFromErrno(xc_error);
+
+ return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
+ "ht_per_core", info.ht_per_core,
+ "cores", info.cores,
+ "total_pages", info.total_pages,
+ "free_pages", info.free_pages,
+ "cpu_khz", info.cpu_khz);
}
static PyMethodDef pyxc_methods[] = {
{ NULL, NULL, 0, NULL }
};
-DL_EXPORT(void) initXc(void)
+PyMODINIT_FUNC initXc(void)
{
- Py_InitModule("Xc", PyXc_methods);
+ PyObject *m, *d;
+
+ m = Py_InitModule("Xc", PyXc_methods);
+
+ d = PyModule_GetDict(m);
+ xc_error = PyErr_NewException("Xc.error", NULL, NULL);
+ PyDict_SetItemString(d, "error", xc_error);
+
+ zero = PyInt_FromLong(0);
}
-import string, re, os, sys
+import os, re, socket, string, sys, tempfile
##### Module variables
return segments
+##### Management of the Xen control daemon
+##### (c) Keir Fraser, University of Cambridge
+
+def xend_control_message( message ):
+ """Takes a textual control message and sends it to the 'xend' Xen
+ control daemon. Returns a dictionary containing the daemon's multi-part
+ response."""
+ tmpdir = tempfile.mkdtemp()
+ try:
+ ctl = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
+ ctl.bind(tmpdir+'/sock')
+ ctl.sendto(message, '/var/run/xend/management_sock')
+ data, addr = ctl.recvfrom(2048)
+ ctl.close()
+ finally:
+ if os.path.exists(tmpdir+'/sock'):
+ os.unlink(tmpdir+'/sock')
+ if os.path.exists(tmpdir):
+ os.rmdir(tmpdir)
+ return eval(data)
+
##### VD Management-related functions
-CC = gcc
-CFLAGS = -Wall -O3
-CFLAGS += -I../xc/lib -I../../xenolinux-sparse/include
-
-HDRS = $(wildcard *.h)
-OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
-
-BIN = xend
-
-all: $(BIN)
+all:
+ python setup.py build
install: all
- mkdir -p $(prefix)/usr/sbin
- cp $(BIN) $(prefix)/usr/sbin
- chmod 755 $(prefix)/usr/sbin/$(BIN)
+ if [ "$(prefix)" = "" ]; then python setup.py install; \
+ else python setup.py install --root "$(prefix)"; fi
+ install --mode=755 xend.py $(prefix)/usr/sbin
+ ln -sf xend.py $(prefix)/usr/sbin/xend
dist: all
- mkdir -p ../../../install/sbin
- cp $(BIN) ../../../install/sbin
- chmod 755 ../../../install/sbin/$(BIN)
+ mkdir -p ../../../../install/lib/python
+ for i in `find . -name 'xend_utils.so'` ; do \
+ install --mode=755 $$i ../../../../install/lib/python/`basename $$i` ; \
+ done
+ python -c 'import py_compile, sys; py_compile.compile("XenoUtil.py")'
+ install --mode=755 xend.py ../../../../install/sbin
+ ln -sf xend.py ../../../../install/sbin/xend
clean:
- $(RM) *.a *.so *.o *.rpm $(BIN)
+ rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm
$(BIN): $(OBJS)
$(CC) -o $@ $^ -L../xc/lib -lxc
--- /dev/null
+
+from distutils.core import setup, Extension
+
+module = Extension("xend_utils",
+ include_dirs = ["../xc/lib",
+ "../../xenolinux-sparse/include"],
+ library_dirs = ["../xc/lib"],
+ libraries = ["xc"],
+ sources = ["xend_utils.c"])
+
+setup(name = "xend_utils", version = "1.0", ext_modules = [module])
--- /dev/null
+#!/usr/bin/env python
+
+
+###########################################################
+## xend.py -- Xen controller daemon
+## Copyright (c) 2004, K A Fraser (University of Cambridge)
+###########################################################
+
+
+import errno, re, os, pwd, select, signal, socket, struct, sys, tempfile, time
+import xend_utils, Xc
+
+
+
+# The following parameters could be placed in a configuration file.
+PID = '/var/run/xend.pid'
+LOG = '/var/log/xend.log'
+USER = 'root'
+CONTROL_DIR = '/var/run/xend'
+UNIX_SOCK = 'management_sock' # relative to CONTROL_DIR
+
+
+
+##
+## console_interface:
+## Each control interface owns an instance of this class, which manages
+## the current state of the console interface. Normally a console interface
+## will be one of two state:
+## LISTENING: listening for a connection on TCP port 'self.port'
+## CONNECTED: sending/receiving console data on TCP port 'self.port'
+##
+## A dictionary of all active interfaces, indexed by TCP socket descriptor,
+## is accessible as 'console_interface.interface_list'.
+##
+## NB. When a class instance is to be destroyed you *must* call the 'close'
+## method. Otherwise a stale reference will eb left in the interface list.
+##
+class console_interface:
+
+ # The various states that a console interface may be in.
+ CLOSED = 0 # No console activity
+ LISTENING = 1 # Listening on port 'self.port'. Socket object 'self.sock'.
+ CONNECTED = 2 # Active connection on 'self.port'. Socket obj 'self.sock'.
+
+
+ # Dictionary of all active (non-closed) console interfaces.
+ interface_list = {}
+
+
+ # NB. 'key' is an opaque value that has no meaning in this class.
+ def __init__(self, port, key):
+ self.status = console_interface.CLOSED
+ self.port = port
+ self.key = key
+
+
+ # Is this interface closed (inactive)?
+ def closed(self):
+ return self.status == console_interface.CLOSED
+
+
+ # Is this interface listening?
+ def listening(self):
+ return self.status == console_interface.LISTENING
+
+
+ # Is this interface active and connected?
+ def connected(self):
+ return self.status == console_interface.CONNECTED
+
+
+ # Close the interface, if it is not closed already.
+ def close(self):
+ if not self.closed():
+ del console_interface.interface_list[self.sock.fileno()]
+ self.sock.close()
+ del self.sock
+ self.status = console_interface.CLOSED
+
+
+ # Move the interface into the 'listening' state. Opens a new listening
+ # socket and updates 'interface_list'.
+ def listen(self):
+ # Close old socket (if any), and create a fresh one.
+ self.close()
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+
+ try:
+ # Turn the new socket into a non-blocking listener.
+ self.sock.setblocking(False)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
+ struct.pack('ii', 0, 0))
+ self.sock.bind(('', self.port))
+ self.sock.listen(1)
+
+ # Announce the new status of thsi interface.
+ self.status = console_interface.LISTENING
+ console_interface.interface_list[self.sock.fileno()] = self
+
+ except:
+ # In case of trouble ensure we get rid of dangling socket reference
+ self.sock.close()
+ del self.sock
+ raise
+
+
+ # Move a listening interface into the 'connected' state.
+ def connect(self):
+ # Pick up a new connection, if one is available.
+ try:
+ (sock, addr) = self.sock.accept()
+ except:
+ return 0
+ sock.setblocking(False)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
+ struct.pack('ii', 0, 0))
+
+ # Close the listening socket.
+ self.sock.close()
+
+ # Publish the new socket and the new interface state.
+ self.sock = sock
+ self.status = console_interface.CONNECTED
+ console_interface.interface_list[self.sock.fileno()] = self
+ return 1
+
+
+
+##
+## new_control_interface:
+## Create a new control interface with the specified domain 'dom'.
+## The console port may also be specified; otehrwise a suitable port is
+## automatically allocated.
+##
+def new_control_interface(dom, console_port=-1):
+ # Allocate an event channel. Clear pending notifications.
+ port = xend_utils.port(dom)
+ notifier.clear(port.local_port, notifier.NORMAL)
+ notifier.clear(port.local_port, notifier.DISCONNECT)
+
+ # If necessary, compute a suitable TCP port for console I/O.
+ if console_port < 0:
+ console_port = 9600 + port.local_port
+
+ # Create a listenign console interface.
+ con_if = console_interface(console_port, port.local_port)
+ con_if.listen()
+
+ # Add control state to the master list.
+ control_list[port.local_port] = \
+ (port, xend_utils.buffer(), xend_utils.buffer(), con_if)
+
+ # Construct the successful response to be returned to the requester.
+ response = { 'success': True }
+ response['local_port'] = port.local_port
+ response['remote_port'] = port.remote_port
+ response['console_port'] = console_port
+ return response
+
+
+
+def daemon_loop():
+ global control_list, notifier
+
+ xc = Xc.new()
+ control_list = {}
+
+ # Ignore writes to disconnected sockets. We clean up differently.
+ signal.signal(signal.SIGPIPE, signal.SIG_IGN)
+
+ # Construct the management interface. This is a UNIX domain socket via
+ # which we receive 'request' datagrams. Each request is a string that
+ # can be eval'ed as a Python statement. Responses can be remotely eval'ed
+ # by the requester to create a Python dictionary of result values.
+ management_interface = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
+ if os.path.exists(CONTROL_DIR+'/'+UNIX_SOCK):
+ os.unlink(CONTROL_DIR+'/'+UNIX_SOCK)
+ management_interface.setblocking(False)
+ management_interface.bind(CONTROL_DIR+'/'+UNIX_SOCK)
+
+ notifier = xend_utils.notifier()
+
+ ##
+ ## MAIN LOOP
+ ##
+ while 1:
+
+ # Construct a poll set. We wait on:
+ # 1. Requests on the management interface.
+ # 2. Incoming event-channel notifications.
+ # Furthermore, for each active control interface:
+ # 3. Incoming console data.
+ # 4. Space for outgoing console data (if there is data to send).
+ waitset = select.poll()
+ waitset.register(management_interface, select.POLLIN)
+ waitset.register(notifier, select.POLLIN)
+ for idx, (port, rbuf, wbuf, con_if) in control_list.items():
+ if not con_if.closed():
+ pflags = select.POLLIN
+ if not rbuf.empty() and con_if.connected():
+ pflags = select.POLLIN | select.POLLOUT
+ waitset.register(con_if.sock.fileno(), pflags)
+
+ # Wait for something to do...
+ fdset = waitset.poll()
+
+ # Look for messages on the management interface.
+ # These should consist of executable Python statements that call
+ # well-known management functions (e.g., new_control_interface(dom=9)).
+ try:
+ data, addr = management_interface.recvfrom(2048)
+ except socket.error, error:
+ if error[0] != errno.EAGAIN:
+ raise
+ else:
+ if addr:
+ # Evaluate the request in an exception-trapping sandbox.
+ try:
+ print "Mgmt_req[%s]: %s" % (addr, data)
+ response = str(eval(data))
+
+ except:
+ # Catch all exceptions and turn into an error response:
+ # status: False
+ # error_type: 'exception'
+ # exception_type: name of exception type.
+ # exception value: textual exception value.
+ exc_type, exc_val = sys.exc_info()[:2]
+ response = { 'success': False }
+ response['error_type'] = 'exception'
+ response['exception_type'] = str(exc_type)
+ response['exception_value'] = str(exc_val)
+ response = str(response)
+
+ # Try to send a response to the requester.
+ try:
+ print "Mgmt_rsp[%s]: %s" % (addr, response)
+ management_interface.sendto(response, addr)
+ except socket.error, error:
+ pass
+
+ # Do work for every console interface that hit in the poll set.
+ for (fd, events) in fdset:
+ if not console_interface.interface_list.has_key(fd):
+ continue
+ con_if = console_interface.interface_list[fd]
+
+ # If the interface is listening, check for pending connections.
+ if con_if.listening():
+ con_if.connect()
+
+ # All done if the interface is not connected.
+ if not con_if.connected():
+ continue
+ (port, rbuf, wbuf, con_if) = control_list[con_if.key]
+
+ # Send as much pending data as possible via the socket.
+ while not rbuf.empty():
+ try:
+ bytes = con_if.sock.send(rbuf.peek())
+ if bytes > 0:
+ rbuf.discard(bytes)
+ except socket.error, error:
+ pass
+
+ # Read as much data as is available. Don't worry about
+ # overflowing our buffer: it's more important to read the
+ # incoming data stream and detect errors or closure of the
+ # remote end in a timely manner.
+ try:
+ while 1:
+ data = con_if.sock.recv(2048)
+ # Return of zero means the remote end has disconnected.
+ # We therefore return the console interface to listening.
+ if not data:
+ con_if.listen()
+ break
+ wbuf.write(data)
+ except socket.error, error:
+ # Assume that most errors mean that the connection is dead.
+ # In such cases we return the interface to 'listening' state.
+ if error[0] != errno.EAGAIN:
+ print "Better return to listening"
+ con_if.listen()
+ print "New status: " + str(con_if.status)
+
+ # We may now have pending data to send via the relevant
+ # inter-domain control interface. If so then we send all we can
+ # and notify the remote end.
+ work_done = False
+ while not wbuf.empty() and port.space_to_write_request():
+ msg = xend_utils.message(0, 0, 0)
+ msg.append_payload(wbuf.read(msg.MAX_PAYLOAD))
+ port.write_request(msg)
+ work_done = True
+ if work_done:
+ port.notify()
+
+ # Process control-interface notifications from other guest OSes.
+ while 1:
+ # Grab a notification, if there is one.
+ notification = notifier.read()
+ if not notification:
+ break
+ (idx, type) = notification
+
+ # If we pick up a disconnect notification then we do any necessary
+ # cleanup, even if the event channel doesn't belong to us.
+ # This is intended to prevent the event-channel port space from
+ # getting clogged with stale connections.
+ if type == notifier.DISCONNECT:
+ ret = xc.evtchn_status(idx)
+ if ret['status'] != 'connected':
+ notifier.clear(idx, notifier.NORMAL)
+ notifier.clear(idx, notifier.DISCONNECT)
+ if control_list.has_key(idx):
+ (port, rbuf, wbuf, con_if) = control_list[idx]
+ con_if.close()
+ del control_list[idx], port, rbuf, wbuf, con_if
+ elif ret['status'] == 'disconnected':
+ # There's noone to do the closure for us...
+ xc.evtchn_close(idx)
+
+ # A standard notification: probably means there are messages to
+ # read or that there is space to write messages.
+ elif type == notifier.NORMAL and control_list.has_key(idx):
+ (port, rbuf, wbuf, con_if) = control_list[idx]
+ work_done = False
+
+ # We clear the notification before doing any work, to avoid
+ # races.
+ notifier.clear(idx, notifier.NORMAL)
+
+ # Read incoming requests. Currently assume that request
+ # message always containb console data.
+ while port.request_to_read():
+ msg = port.read_request()
+ rbuf.write(msg.get_payload())
+ port.write_response(msg)
+ work_done = True
+
+ # Incoming responses are currently thrown on the floor.
+ while port.response_to_read():
+ msg = port.read_response()
+ work_done = True
+
+ # Send as much pending console data as there is room for.
+ while not wbuf.empty() and port.space_to_write_request():
+ msg = xend_utils.message(0, 0, 0)
+ msg.append_payload(wbuf.read(msg.MAX_PAYLOAD))
+ port.write_request(msg)
+ work_done = True
+
+ # Finally, notify the remote end of any work that we did.
+ if work_done:
+ port.notify()
+
+
+
+def cleanup_daemon(kill=False):
+ # No cleanup to do if the PID file is empty.
+ if not os.path.isfile(PID) or not os.path.getsize(PID):
+ return 0
+ # Read the PID of the previous invocation and search active process list.
+ pid = open(PID, 'r').read()
+ lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
+ for line in lines:
+ if re.search('^ *' + pid + '.+xend', line):
+ if not kill:
+ print "Daemon is already running (PID %d)" % int(pid)
+ return 1
+ # Old daemon is still active: terminate it.
+ os.kill(int(pid), 1)
+ # Delete the, now stale, PID file.
+ os.remove(PID)
+ return 0
+
+
+
+def start_daemon():
+ if cleanup_daemon(kill=False):
+ return 1
+
+ if not os.path.exists(CONTROL_DIR):
+ os.mkdir(CONTROL_DIR)
+
+ # Open log file. Truncate it if non-empty, and request line buffering.
+ if os.path.isfile(LOG):
+ os.rename(LOG, LOG+'.old')
+ logfile = open(LOG, 'w+', 1)
+
+ # Detach from TTY.
+ os.setsid()
+
+ # Set the UID.
+ try:
+ os.setuid(pwd.getpwnam(USER)[2])
+ except KeyError, error:
+ print "Error: no such user '%s'" % USER
+ return 1
+
+ # Ensure that zombie children are automatically reaped.
+ xend_utils.autoreap()
+
+ # Fork -- parent writes the PID file and exits.
+ pid = os.fork()
+ if pid:
+ pidfile = open(PID, 'w')
+ pidfile.write(str(pid))
+ pidfile.close()
+ return 0
+
+ # Close down standard file handles
+ try:
+ os.close(0) # stdin
+ os.close(1) # stdout
+ os.close(2) # stderr
+ except:
+ pass
+
+ # Redirect output to log file, then enter the main loop.
+ sys.stdout = sys.stderr = logfile
+ daemon_loop()
+ return 0
+
+
+
+def stop_daemon():
+ return cleanup_daemon(kill=True)
+
+
+
+def main():
+ xend_utils.autoreap()
+ if not sys.argv[1:]:
+ print 'usage: %s {start|stop|restart}' % sys.argv[0]
+ elif os.fork():
+ pid, status = os.wait()
+ return status >> 8
+ elif sys.argv[1] == 'start':
+ return start_daemon()
+ elif sys.argv[1] == 'stop':
+ return stop_daemon()
+ elif sys.argv[1] == 'restart':
+ return stop_daemon() or start_daemon()
+ else:
+ print 'not an option:', sys.argv[1]
+ return 1
+
+
+
+if __name__ == '__main__':
+ sys.exit(main())
/******************************************************************************
- * xend.c
- *
- * The grand Xen daemon. For now it's just a virtual-console concentrator.
+ * xend_utils.c
*
* Copyright (c) 2004, K A Fraser
*/
+#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/mman.h>
#define PORTIDX_MASK 0x7fff /* Strip subtype to obtain port index. */
#define EVTCHN_RESET _IO('E', 1) /* Clear notification buffer. Clear errors. */
-/* Error macros. */
-#define ERROR(_f, _a...) \
- fprintf ( stderr, "ERROR: " _f "\n" , ## _a );
-#define SYS_ERROR(_f, _a...) \
- fprintf ( stderr, "ERROR: " _f " [errno=%d (%s)]\n" , \
- ## _a , errno , strerror(errno) );
-#define HINT(_f, _a...) \
- fprintf ( stderr, "Hint: " _f "\n" , ## _a );
-#define ROOT_HINT() HINT("You must execute this daemon as root.")
-#define DOM0_HINT() HINT("You must execute this daemon " \
- "on a privileged Xenolinux instance (e.g., DOM0).")
-
-#if 0
-#define DPRINTF(_f, _a...) \
- fprintf ( stdout, _f "\n" , ## _a );
-#else
-#define DPRINTF(_f, _a...) ((void)0)
-#endif
-
-/* Per-port Tx/Rx buffering. */
-#define CONBUFSZ 65536
-#define MASK_CONBUF_IDX(_i) ((_i)&(CONBUFSZ-1))
-
-struct portinfo;
-typedef struct portinfo {
- u64 dom;
- control_if_t *interface;
- CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
- CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
- char *tx_buf, *rx_buf;
- unsigned int txp, txc, rxp, rxc;
-#define CONSTAT_CLOSED 0
-#define CONSTAT_LISTENING 1
-#define CONSTAT_CONNECTED 2
- int con_fd, con_status;
- struct portinfo **pprev, *next; /* links to other active ports */
-} portinfo_t;
-
-#define PORT(_pinfo) ((_pinfo)-portinfo)
-#define TX_EMPTY(_pinfo) ((_pinfo)->txp == (_pinfo)->txc)
-#define TX_FULL(_pinfo) (((_pinfo)->txp - (_pinfo)->txc) == CONBUFSZ)
-#define RX_EMPTY(_pinfo) ((_pinfo)->rxp == (_pinfo)->rxc)
-#define RX_FULL(_pinfo) (((_pinfo)->rxp - (_pinfo)->rxc) == CONBUFSZ)
-
-static portinfo_t *active_head; /* linked list of active ports */
-static portinfo_t portinfo[1024]; /* array of all ports */
-static int xc_fd, evt_fd, mem_fd;
-
-#define PAGE_SIZE 4096 /* size of a machine page frame */
-#define BATCH_SIZE 512 /* maximum notifications to read at a time */
-
-static int make_consock_listener(portinfo_t *pinfo);
-static int make_consock_connected(portinfo_t *pinfo);
-static void make_consock_closed(portinfo_t *pinfo);
-static void do_consock_read(portinfo_t *pinfo);
-static void do_consock_write(portinfo_t *pinfo);
-static int process_evtchn_reads(portinfo_t *pinfo);
-static int process_evtchn_writes(portinfo_t *pinfo);
+/* Size of a machine page frame. */
+#define PAGE_SIZE 4096
+
+
+/*
+ * *********************** NOTIFIER ***********************
+ */
+
+typedef struct {
+ PyObject_HEAD;
+ int evtchn_fd;
+} xu_notifier_object;
+
+static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ u16 v;
+ int bytes;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
+ {
+ if ( errno == EINTR )
+ continue;
+ if ( errno == EAGAIN )
+ goto none;
+ return PyErr_SetFromErrno(PyExc_IOError);
+ }
+
+ if ( bytes == sizeof(v) )
+ return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
+
+ none:
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_notifier_clear(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ u16 v;
+ int idx, type;
+
+ if ( !PyArg_ParseTuple(args, "ii", &idx, &type) )
+ return NULL;
+
+ v = (u16)idx | (u16)type;
+
+ (void)write(xun->evtchn_fd, &v, sizeof(v));
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ return PyInt_FromLong(xun->evtchn_fd);
+}
+
+static PyMethodDef xu_notifier_methods[] = {
+ { "read",
+ (PyCFunction)xu_notifier_read,
+ METH_VARARGS,
+ "Read a (@port, @type) pair.\n" },
+
+ { "clear",
+ (PyCFunction)xu_notifier_clear,
+ METH_VARARGS,
+ "Clear a (@port, @type) pair.\n" },
+
+ { "fileno",
+ (PyCFunction)xu_notifier_fileno,
+ METH_VARARGS,
+ "Return the file descriptor for the notification channel.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_notifier_type;
+
+static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
+{
+ xu_notifier_object *xun;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
+
+ xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
+ if ( xun->evtchn_fd == -1 )
+ {
+ PyObject_Del((PyObject *)xun);
+ return PyErr_SetFromErrno(PyExc_IOError);
+ }
+
+ return (PyObject *)xun;
+}
+
+static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
+{
+ if ( strcmp(name, "DISCONNECT") == 0 )
+ return PyInt_FromLong(PORT_DISCONNECT);
+ if ( strcmp(name, "NORMAL") == 0 )
+ return PyInt_FromLong(PORT_NORMAL);
+ return Py_FindMethod(xu_notifier_methods, obj, name);
+}
+
+static void xu_notifier_dealloc(PyObject *self)
+{
+ xu_notifier_object *xun = (xu_notifier_object *)self;
+ (void)close(xun->evtchn_fd);
+ PyObject_Del(self);
+}
+
+static PyTypeObject xu_notifier_type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "notifier",
+ sizeof(xu_notifier_object),
+ 0,
+ xu_notifier_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ xu_notifier_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+
+
+/*
+ * *********************** MESSAGE ***********************
+ */
+
+typedef struct {
+ PyObject_HEAD;
+ control_msg_t msg;
+} xu_message_object;
+
+static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum = (xu_message_object *)self;
+ char *str;
+ int len;
+
+ if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+ return NULL;
+
+ if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
+ {
+ PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
+ return NULL;
+ }
+
+ memcpy(&xum->msg.msg[xum->msg.length], str, len);
+ xum->msg.length += len;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum = (xu_message_object *)self;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
+}
+
+static PyObject *xu_message_set_header(PyObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ xu_message_object *xum = (xu_message_object *)self;
+ int type = -1, subtype = -1, id = -1;
+
+ static char *kwd_list[] = { "type", "subtype", "id", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwd_list,
+ &type, &subtype, &id) )
+ return NULL;
+
+ if ( type != -1 )
+ xum->msg.type = (u8)type;
+ if ( subtype != -1 )
+ xum->msg.subtype = (u8)subtype;
+ if ( id != -1 )
+ xum->msg.id = (u8)id;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum = (xu_message_object *)self;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ return Py_BuildValue("{s:i,s:i,s:i}",
+ "type", xum->msg.type,
+ "subtype", xum->msg.subtype,
+ "id", xum->msg.id);
+}
+
+static PyMethodDef xu_message_methods[] = {
+ { "append_payload",
+ (PyCFunction)xu_message_append_payload,
+ METH_VARARGS,
+ "Append @str to the message payload.\n" },
+
+ { "get_payload",
+ (PyCFunction)xu_message_get_payload,
+ METH_VARARGS,
+ "Return the message payload in string form.\n" },
+
+ { "set_header",
+ (PyCFunction)xu_message_set_header,
+ METH_VARARGS | METH_KEYWORDS,
+ "Accepts keywords @type, @subtype, and @id.\n" },
+
+ { "get_header",
+ (PyCFunction)xu_message_get_header,
+ METH_VARARGS,
+ "Returns a dictionary of values for @type, @subtype, and @id.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_message_type;
+
+static PyObject *xu_message_new(PyObject *self, PyObject *args)
+{
+ xu_message_object *xum;
+ int type, subtype, id;
+
+ if ( !PyArg_ParseTuple(args, "iii", &type, &subtype, &id) )
+ return NULL;
+
+ xum = PyObject_New(xu_message_object, &xu_message_type);
+
+ xum->msg.type = type;
+ xum->msg.subtype = subtype;
+ xum->msg.id = id;
+ xum->msg.length = 0;
+
+ return (PyObject *)xum;
+}
+
+static PyObject *xu_message_getattr(PyObject *obj, char *name)
+{
+ xu_message_object *xum;
+ if ( strcmp(name, "MAX_PAYLOAD") == 0 )
+ return PyInt_FromLong(sizeof(xum->msg.msg));
+ return Py_FindMethod(xu_message_methods, obj, name);
+}
+
+static void xu_message_dealloc(PyObject *self)
+{
+ PyObject_Del(self);
+}
+
+static PyTypeObject xu_message_type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "message",
+ sizeof(xu_message_object),
+ 0,
+ xu_message_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ xu_message_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+
+
+/*
+ * *********************** PORT ***********************
+ */
static control_if_t *map_control_interface(int fd, unsigned long pfn)
{
return NULL;
return (control_if_t *)(vaddr + 2048);
}
-
static void unmap_control_interface(int fd, control_if_t *c)
{
char *vaddr = (char *)c - 2048;
(void)munmap(vaddr, PAGE_SIZE);
}
-/* Returns TRUE if the channel is open on exit. */
-static int handle_channel_exception(unsigned int port)
+typedef struct {
+ PyObject_HEAD;
+ int mem_fd;
+ int xc_handle;
+ u64 remote_dom;
+ int local_port, remote_port;
+ control_if_t *interface;
+ CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
+ CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
+} xu_port_object;
+
+static PyObject *port_error;
+
+static PyObject *xu_port_notify(PyObject *self, PyObject *args)
{
- xc_dominfo_t info;
- unsigned int remote_port, status;
- u64 remote_dom;
- u16 wbuf;
- portinfo_t *pinfo = &portinfo[port];
+ xu_port_object *xup = (xu_port_object *)self;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ xu_message_object *xum;
+ CONTROL_RING_IDX c = xup->tx_req_cons;
+ control_if_t *cif = xup->interface;
+ control_msg_t *cmsg;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
- if ( xc_evtchn_status(xc_fd, DOMID_SELF, port,
- &remote_dom, &remote_port, &status) != 0 )
+ if ( (c == cif->tx_req_prod) ||
+ ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
{
- SYS_ERROR("Unexpected failure when obtaining port-%d status.", port);
- exit(1);
+ PyErr_SetString(port_error, "no request to read");
+ return NULL;
}
-
- if ( status != EVTCHNSTAT_connected )
+
+ cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+ xum = PyObject_New(xu_message_object, &xu_message_type);
+ memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+ if ( xum->msg.length > sizeof(xum->msg.msg) )
+ xum->msg.length = sizeof(xum->msg.msg);
+ xup->tx_req_cons++;
+ return (PyObject *)xum;
+}
+
+static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ xu_message_object *xum;
+ CONTROL_RING_IDX p = xup->rx_req_prod;
+ control_if_t *cif = xup->interface;
+ control_msg_t *cmsg;
+
+ if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+ return NULL;
+
+ if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
{
- DPRINTF("Port %d not connected: cleaning up.", port);
- if ( pinfo->interface != NULL )
- {
- unmap_control_interface(mem_fd, pinfo->interface);
- pinfo->interface = NULL;
- *(pinfo->pprev) = pinfo->next;
- if ( pinfo->next != NULL )
- pinfo->next->pprev = pinfo->pprev;
- make_consock_closed(pinfo);
- free(pinfo->tx_buf);
- free(pinfo->rx_buf);
- memset(pinfo, 0, sizeof(*pinfo));
- }
- /* Cleanup sanity: we'll be the grim reaper. */
- wbuf = port | PORT_NORMAL;
- (void)write(evt_fd, &wbuf, sizeof(wbuf));
- wbuf = port | PORT_DISCONNECT;
- (void)write(evt_fd, &wbuf, sizeof(wbuf));
- if ( status == EVTCHNSTAT_disconnected )
- (void)xc_evtchn_close(xc_fd, DOMID_SELF, port);
- return 0;
+ PyErr_SetString(PyExc_TypeError, "expected a xend_utils.message");
+ return NULL;
}
- /* We only deal with initial ports (id == 0). */
- if ( remote_port != 0 )
- return 0;
-
- if ( pinfo->interface == NULL )
+ if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
{
- DPRINTF("New control interface for DOM%llu on port %d.",
- remote_dom, port);
- if ( xc_domain_getinfo(xc_fd, remote_dom, 1, &info) != 1 )
- {
- SYS_ERROR("Failed to obtain DOM%llu status.", remote_dom);
- exit(1);
- }
- memset(pinfo, 0, sizeof(*pinfo));
- pinfo->interface =
- map_control_interface(mem_fd, info.shared_info_frame);
- pinfo->tx_buf = malloc(CONBUFSZ);
- pinfo->rx_buf = malloc(CONBUFSZ);
- pinfo->dom = remote_dom;
- pinfo->con_status = CONSTAT_CLOSED;
- if ( !make_consock_listener(pinfo) )
- {
- ERROR("Could not start console %d in listener status.",
- PORT(pinfo));
- exit(1);
- }
- pinfo->pprev = &active_head;
- if ( (pinfo->next = active_head) != NULL )
- pinfo->next->pprev = &pinfo->next;
- active_head = pinfo;
+ PyErr_SetString(port_error, "no space to write request");
+ return NULL;
}
- return 1;
+ cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
+ memcpy(cmsg, &xum->msg, sizeof(*cmsg));
+
+ xup->rx_req_prod = cif->rx_req_prod = p + 1;
+
+ Py_INCREF(Py_None);
+ return Py_None;
}
-static void process_channel(unsigned int port)
+static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
{
- portinfo_t *pinfo = &portinfo[port];
- u16 wbuf = port;
+ xu_port_object *xup = (xu_port_object *)self;
+ xu_message_object *xum;
+ CONTROL_RING_IDX c = xup->rx_resp_cons;
+ control_if_t *cif = xup->interface;
+ control_msg_t *cmsg;
- /* Acknowledge the notification. */
- (void)write(evt_fd, &wbuf, sizeof(wbuf));
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
- /* Process requests; send notification if we updated either ring. */
- if ( process_evtchn_reads(pinfo) || process_evtchn_writes(pinfo) )
- (void)xc_evtchn_send(xc_fd, port);
+ if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+ {
+ PyErr_SetString(port_error, "no response to read");
+ return NULL;
+ }
+
+ cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
+ xum = PyObject_New(xu_message_object, &xu_message_type);
+ memcpy(&xum->msg, cmsg, sizeof(*cmsg));
+ if ( xum->msg.length > sizeof(xum->msg.msg) )
+ xum->msg.length = sizeof(xum->msg.msg);
+ xup->rx_resp_cons++;
+ return (PyObject *)xum;
}
-int main(int argc, char **argv)
+static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
{
- struct pollfd polls[1025]; /* one per port, plus /dev/xeno/evtchn */
- portinfo_t *pinfo;
- unsigned int batch, bytes, i, port, fd_idx;
- u16 buf[BATCH_SIZE];
+ xu_port_object *xup = (xu_port_object *)self;
+ xu_message_object *xum;
+ CONTROL_RING_IDX p = xup->tx_resp_prod;
+ control_if_t *cif = xup->interface;
+ control_msg_t *cmsg;
- /* Ignore writes to disconnected sockets. We clear up later. */
- (void)signal(SIGPIPE, SIG_IGN);
-
- if ( (evt_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR)) == -1 )
- {
- SYS_ERROR("Could not open '%s'", EVTCHN_DEV_NAME);
- ROOT_HINT();
- HINT("On a non-devfs system you must run 'mknod %s c %d %d'.",
- EVTCHN_DEV_NAME, EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR);
- exit(1);
- }
+ if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
+ return NULL;
- if ( (mem_fd = open("/dev/mem", O_RDWR)) == -1 )
+ if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
{
- SYS_ERROR("Could not open '/dev/mem'");
- ROOT_HINT();
- exit(1);
+ PyErr_SetString(PyExc_TypeError, "expected a xend_utils.message");
+ return NULL;
}
- if ( (xc_fd = xc_interface_open()) == -1 )
+ if ( p == xup->tx_req_cons )
{
- SYS_ERROR("Could not open Xen control interface");
- ROOT_HINT();
- DOM0_HINT();
- exit(1);
+ PyErr_SetString(port_error, "no space to write response");
+ return NULL;
}
- for ( ; ; )
- {
- polls[0].fd = evt_fd;
- polls[0].events = POLLIN;
+ cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
+ memcpy(cmsg, &xum->msg, sizeof(*cmsg));
- fd_idx = 1;
- for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
- {
- switch ( pinfo->con_status )
- {
- case CONSTAT_LISTENING:
- polls[fd_idx].fd = pinfo->con_fd;
- polls[fd_idx].events = POLLIN;
- fd_idx++;
- break;
- case CONSTAT_CONNECTED:
- polls[fd_idx].fd = pinfo->con_fd;
- polls[fd_idx].events = POLLIN | (RX_EMPTY(pinfo)?0:POLLOUT);
- fd_idx++;
- break;
- }
- }
+ xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
- while ( poll(polls, fd_idx, -1) == -1 )
- {
- if ( errno == EINTR )
- continue;
- SYS_ERROR("Unexpected error from poll().");
- exit(1);
- }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
- fd_idx = 1;
- for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
- {
- switch ( pinfo->con_status )
- {
- case CONSTAT_LISTENING:
- if ( ((polls[fd_idx].revents & POLLIN) != 0) )
- (void)make_consock_connected(pinfo);
- break;
- case CONSTAT_CONNECTED:
- if ( ((polls[fd_idx].revents & POLLOUT) != 0) )
- do_consock_write(pinfo);
- if ( ((polls[fd_idx].revents & POLLIN) != 0) )
- do_consock_read(pinfo);
- break;
- }
- fd_idx++;
- }
+static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ CONTROL_RING_IDX c = xup->tx_req_cons;
+ control_if_t *cif = xup->interface;
- while ( (bytes = read(evt_fd, buf, sizeof(buf))) == -1 )
- {
- if ( errno == EINTR )
- continue;
- if ( errno == EAGAIN )
- {
- bytes = 0;
- break;
- }
- SYS_ERROR("Unexpected error while reading '%s'.", EVTCHN_DEV_NAME);
- exit(1);
- }
-
- if ( bytes == 0 )
- continue;
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
- if ( (bytes & 1) != 0 )
- {
- ERROR("Bad read length (%d bytes) from '%s'.",
- bytes, EVTCHN_DEV_NAME);
- exit(1);
- }
-
- batch = bytes / sizeof(u16);
- for ( i = 0; i < batch; i++ )
- {
- port = buf[i] & PORTIDX_MASK;
-
- if ( buf[i] & PORT_DISCONNECT )
- {
- DPRINTF("Disconnect on port %d.", port);
- (void)handle_channel_exception(port);
- continue;
- }
-
- if ( portinfo[port].interface == NULL )
- {
- DPRINTF("Unexpected notification on port %d.", port);
- if ( !handle_channel_exception(port) )
- continue;
- }
-
- process_channel(port);
- }
- }
+ if ( (c == cif->tx_req_prod) ||
+ ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
+ return PyInt_FromLong(0);
+
+ return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ CONTROL_RING_IDX p = xup->rx_req_prod;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
- (void)xc_interface_close(xc_fd);
- (void)close(mem_fd);
- (void)close(evt_fd);
+ if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
+ return PyInt_FromLong(0);
- return 0;
+ return PyInt_FromLong(1);
}
+static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ CONTROL_RING_IDX c = xup->rx_resp_cons;
+ control_if_t *cif = xup->interface;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
+ return PyInt_FromLong(0);
-/* Returns non-zero if console is listening on exit. */
-static int make_consock_listener(portinfo_t *pinfo)
+ return PyInt_FromLong(1);
+}
+
+static PyObject *xu_port_space_to_write_response(
+ PyObject *self, PyObject *args)
{
- int reuseaddr_flag = 1;
- struct linger linger;
- int tcp_port = 9600 + PORT(pinfo);
- int fd, flags;
- struct sockaddr_in sa;
+ xu_port_object *xup = (xu_port_object *)self;
+ CONTROL_RING_IDX p = xup->tx_resp_prod;
- if ( pinfo->con_status == CONSTAT_LISTENING )
- return 1;
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
- if ( pinfo->con_status == CONSTAT_CONNECTED )
- {
- (void)close(pinfo->con_fd);
- pinfo->con_status = CONSTAT_CLOSED;
- }
+ if ( p == xup->tx_req_cons )
+ return PyInt_FromLong(0);
+
+ return PyInt_FromLong(1);
+}
+
+static PyMethodDef xu_port_methods[] = {
+ { "notify",
+ (PyCFunction)xu_port_notify,
+ METH_VARARGS,
+ "Send a notification to the remote end.\n" },
+
+ { "read_request",
+ (PyCFunction)xu_port_read_request,
+ METH_VARARGS,
+ "Read a request message from the control interface.\n" },
+
+ { "write_request",
+ (PyCFunction)xu_port_write_request,
+ METH_VARARGS,
+ "Write a request message to the control interface.\n" },
+
+ { "read_response",
+ (PyCFunction)xu_port_read_response,
+ METH_VARARGS,
+ "Read a response message from the control interface.\n" },
+
+ { "write_response",
+ (PyCFunction)xu_port_write_response,
+ METH_VARARGS,
+ "Write a response message to the control interface.\n" },
+
+ { "request_to_read",
+ (PyCFunction)xu_port_request_to_read,
+ METH_VARARGS,
+ "Returns TRUE if there is a request message to read.\n" },
+
+ { "space_to_write_request",
+ (PyCFunction)xu_port_space_to_write_request,
+ METH_VARARGS,
+ "Returns TRUE if there is space to write a request message.\n" },
+
+ { "response_to_read",
+ (PyCFunction)xu_port_response_to_read,
+ METH_VARARGS,
+ "Returns TRUE if there is a response message to read.\n" },
+
+ { "space_to_write_response",
+ (PyCFunction)xu_port_space_to_write_response,
+ METH_VARARGS,
+ "Returns TRUE if there is space to write a response message.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_port_type;
+
+static PyObject *xu_port_new(PyObject *self, PyObject *args)
+{
+ xu_port_object *xup;
+ u64 dom;
+ int port1, port2;
+ xc_dominfo_t info;
+
+ if ( !PyArg_ParseTuple(args, "L", &dom) )
+ return NULL;
+
+ xup = PyObject_New(xu_port_object, &xu_port_type);
- if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
+ if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
{
- SYS_ERROR("Could not create TCP socket.");
- return 0;
+ PyErr_SetString(port_error, "Could not open '/dev/mem'");
+ goto fail1;
}
- linger.l_onoff = 0;
- if ( (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- &reuseaddr_flag, sizeof(int)) != 0) ||
- (setsockopt(fd, SOL_SOCKET, SO_LINGER,
- &linger, sizeof(linger)) != 0) )
+ if ( (xup->xc_handle = xc_interface_open()) == -1 )
{
- SYS_ERROR("Could not enable immediate reuse of socket port.");
- close(fd);
- return 0;
+ PyErr_SetString(port_error, "Could not open Xen control interface");
+ goto fail2;
}
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = htonl(INADDR_ANY);
- sa.sin_port = htons(tcp_port);
- if ( bind(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 )
+ if ( xc_evtchn_open(xup->xc_handle, DOMID_SELF, dom, &port1, &port2) != 0 )
{
- SYS_ERROR("Unable to bind to console port %d.", tcp_port);
- close(fd);
- return 0;
+ PyErr_SetString(port_error, "Could not open channel to domain");
+ goto fail3;
}
- if ( listen(fd, 5) != 0 )
+ if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
+ (info.domid != dom) )
{
- SYS_ERROR("Unable to listen on console port %d.", tcp_port);
- close(fd);
- return 0;
+ PyErr_SetString(port_error, "Failed to obtain domain status");
+ goto fail4;
}
- if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
- (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
+ xup->interface =
+ map_control_interface(xup->mem_fd, info.shared_info_frame);
+ if ( xup->interface == NULL )
{
- SYS_ERROR("Unable to set non-blocking status for console listener.");
- close(fd);
- return 0;
+ PyErr_SetString(port_error, "Failed to map domain control interface");
+ goto fail4;
}
- pinfo->con_fd = fd;
- pinfo->con_status = CONSTAT_LISTENING;
- return 1;
+ xup->tx_req_cons = 0;
+ xup->tx_resp_prod = 0;
+ xup->rx_req_prod = 0;
+ xup->rx_resp_cons = 0;
+ xup->remote_dom = dom;
+ xup->local_port = port1;
+ xup->remote_port = port2;
+
+ return (PyObject *)xup;
+
+
+ fail4:
+ (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
+ fail3:
+ (void)xc_interface_close(xup->xc_handle);
+ fail2:
+ (void)close(xup->mem_fd);
+ fail1:
+ PyObject_Del((PyObject *)xup);
+ return NULL;
}
-/* Returns non-zero if console is connected on exit. */
-static int make_consock_connected(portinfo_t *pinfo)
+static PyObject *xu_port_getattr(PyObject *obj, char *name)
{
- int fd, flags, sa_len;
- struct linger linger;
- struct sockaddr_in sa;
+ xu_port_object *xup = (xu_port_object *)obj;
+ if ( strcmp(name, "local_port") == 0 )
+ return PyInt_FromLong(xup->local_port);
+ if ( strcmp(name, "remote_port") == 0 )
+ return PyInt_FromLong(xup->remote_port);
+ if ( strcmp(name, "remote_dom") == 0 )
+ return PyLong_FromUnsignedLongLong(xup->remote_dom);
+ return Py_FindMethod(xu_port_methods, obj, name);
+}
- if ( pinfo->con_status == CONSTAT_CONNECTED )
- return 1;
+static void xu_port_dealloc(PyObject *self)
+{
+ xu_port_object *xup = (xu_port_object *)self;
+ unmap_control_interface(xup->mem_fd, xup->interface);
+ (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
+ (void)xc_interface_close(xup->xc_handle);
+ (void)close(xup->mem_fd);
+ PyObject_Del(self);
+}
- if ( pinfo->con_status == CONSTAT_CLOSED )
- return 0;
+static PyTypeObject xu_port_type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "port",
+ sizeof(xu_port_object),
+ 0,
+ xu_port_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ xu_port_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+
+
+/*
+ * *********************** BUFFER ***********************
+ */
- if ( (fd = accept(pinfo->con_fd, (struct sockaddr *)&sa, &sa_len)) == -1 )
- return 0;
+#define BUFSZ 65536
+#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
+typedef unsigned int BUF_IDX;
- linger.l_onoff = 0;
- if ( setsockopt(fd, SOL_SOCKET, SO_LINGER,
- &linger, sizeof(linger)) != 0 )
- {
- SYS_ERROR("Could not enable immediate socket death.");
- close(fd);
- return 0;
- }
+typedef struct {
+ PyObject_HEAD;
+ char *buf;
+ unsigned int prod, cons;
+} xu_buffer_object;
- if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
- (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
+static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
+{
+ PyObject *str1, *str2;
+ int len1, len2, c = MASK_BUF_IDX(xub->cons);
+
+ len1 = xub->prod - xub->cons;
+ if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
+ len1 = BUFSZ - c;
+ if ( len1 > max ) /* clip to specified maximum */
+ len1 = max;
+ if ( len1 < 0 ) /* sanity */
+ len1 = 0;
+
+ if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
+ return NULL;
+
+ if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
{
- SYS_ERROR("Unable to set non-blocking status on socket.");
- close(fd);
- return 0;
+ len2 = max - len1;
+ if ( len2 > MASK_BUF_IDX(xub->prod) )
+ len2 = MASK_BUF_IDX(xub->prod);
+ if ( len2 > 0 )
+ {
+ str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
+ if ( str2 == NULL )
+ return NULL;
+ PyString_ConcatAndDel(&str1, str2);
+ if ( str1 == NULL )
+ return NULL;
+ }
}
- (void)close(pinfo->con_fd);
-
- pinfo->con_fd = fd;
- pinfo->con_status = CONSTAT_CONNECTED;
- return 1;
+ return str1;
}
+static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ int max = 1024;
-static void make_consock_closed(portinfo_t *pinfo)
+ if ( !PyArg_ParseTuple(args, "|i", &max) )
+ return NULL;
+
+ return __xu_buffer_peek(xub, max);
+}
+
+static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
{
- if ( pinfo->con_status != CONSTAT_CLOSED )
- (void)close(pinfo->con_fd);
- pinfo->con_status = CONSTAT_CLOSED;
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ PyObject *str;
+ int max = 1024;
+
+ if ( !PyArg_ParseTuple(args, "|i", &max) )
+ return NULL;
+
+ if ( (str = __xu_buffer_peek(xub, max)) != NULL )
+ xub->cons += PyString_Size(str);
+
+ return str;
}
+static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ int max, len;
+
+ if ( !PyArg_ParseTuple(args, "i", &max) )
+ return NULL;
+
+ len = xub->prod - xub->cons;
+ if ( len > max )
+ len = max;
+ if ( len < 0 )
+ len = 0;
+
+ xub->cons += len;
+
+ return PyInt_FromLong(len);
+}
-static void do_consock_read(portinfo_t *pinfo)
+static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
{
- char buf[1024];
- int idx, bytes, rc, was_empty = TX_EMPTY(pinfo);
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ char *str;
+ int len, len1, len2;
- while ( (rc = read(pinfo->con_fd, &buf, sizeof(buf))) > 0 )
- {
- idx = 0;
- while ( (rc != 0) && !TX_FULL(pinfo) )
- {
- bytes = rc;
- /* Clip copy to ring-buffer wrap. */
- if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp)) )
- bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp);
- /* Clip copy to ring-buffer overflow. */
- if ( bytes > (CONBUFSZ - (pinfo->txp - pinfo->txc)) )
- bytes = CONBUFSZ - (pinfo->txp - pinfo->txc);
- memcpy(&pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txp)],
- &buf[idx], bytes);
- pinfo->txp += bytes;
- idx += bytes;
- rc -= bytes;
- }
- }
+ if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
+ return NULL;
+
+ len1 = len;
+ if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+ len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
+ if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
+ len1 = BUFSZ - (xub->prod - xub->cons);
+
+ if ( len1 == 0 )
+ return PyInt_FromLong(0);
- if ( (rc == 0) || (errno != EAGAIN) )
+ memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
+ xub->prod += len1;
+
+ if ( len1 < len )
{
- DPRINTF("Console client has disconnected.");
- if ( !make_consock_listener(pinfo) )
+ len2 = len - len1;
+ if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
+ len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
+ if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
+ len2 = BUFSZ - (xub->prod - xub->cons);
+ if ( len2 != 0 )
{
- ERROR("Could not revert console %d to listener status.",
- PORT(pinfo));
- exit(1);
+ memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
+ xub->prod += len2;
+ return PyInt_FromLong(len1 + len2);
}
}
- if ( was_empty && !TX_EMPTY(pinfo) )
- {
- /* There is now data to transmit to guest. Kickstart the pipeline. */
- if ( process_evtchn_writes(pinfo) )
- (void)xc_evtchn_send(xc_fd, PORT(pinfo));
- }
+ return PyInt_FromLong(len1);
}
-static void do_consock_write(portinfo_t *pinfo)
+static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
{
- int bytes, rc;
+ xu_buffer_object *xub = (xu_buffer_object *)self;
- while ( !RX_EMPTY(pinfo) )
- {
- /* Clip transfer to ring-buffer wrap. */
- bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxc);
- /* Clip transfer to ring-buffer overflow. */
- if ( bytes > (pinfo->rxp - pinfo->rxc) )
- bytes = pinfo->rxp - pinfo->rxc;
- rc = write(pinfo->con_fd,
- &pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxc)],
- bytes);
- if ( rc <= 0 )
- return; /* Nothing to do. Errors cleaned up in reader code. */
- pinfo->rxc += rc;
- }
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ if ( xub->cons == xub->prod )
+ return PyInt_FromLong(1);
+
+ return PyInt_FromLong(0);
}
-static int process_evtchn_reads(portinfo_t *pinfo)
+static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
{
- CONTROL_RING_IDX c;
- control_if_t *cif = pinfo->interface;
- control_msg_t *cmsg;
- unsigned int clen, idx, len, bytes;
+ xu_buffer_object *xub = (xu_buffer_object *)self;
- for ( c = pinfo->tx_req_cons;
- (c != cif->tx_req_prod) &&
- ((c-pinfo->tx_resp_prod) != CONTROL_RING_SIZE);
- c++ )
- {
- cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
- if ( (clen = cmsg->length) > sizeof(cmsg->msg) )
- clen = sizeof(cmsg->msg);
+ if ( (xub->prod - xub->cons) == BUFSZ )
+ return PyInt_FromLong(1);
- if ( (cmsg->cmd_type == CMD_CONSOLE) &&
- (cmsg->cmd_subtype == CMD_CONSOLE_DATA) )
- {
- idx = 0;
- len = cmsg->length;
- while ( (len != 0) && !RX_FULL(pinfo) )
- {
- bytes = len;
- /* Clip copy to ring-buffer wrap. */
- if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp)) )
- bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp);
- /* Clip copy to ring-buffer overflow. */
- if ( bytes > (CONBUFSZ - (pinfo->rxp - pinfo->rxc)) )
- bytes = CONBUFSZ - (pinfo->rxp - pinfo->rxc);
- memcpy(&pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxp)],
- &cmsg->msg[idx], bytes);
- pinfo->rxp += bytes;
- idx += bytes;
- len -= bytes;
- }
- }
+ return PyInt_FromLong(0);
+}
- /* Prepare response. No payload; msg type and id same as request. */
- cmsg->length = 0;
- }
+static PyMethodDef xu_buffer_methods[] = {
+ { "peek",
+ (PyCFunction)xu_buffer_peek,
+ METH_VARARGS,
+ "Peek up to @max bytes from the buffer. Returns a string.\n" },
- if ( c != pinfo->tx_req_cons )
+ { "read",
+ (PyCFunction)xu_buffer_read,
+ METH_VARARGS,
+ "Read up to @max bytes from the buffer. Returns a string.\n" },
+
+ { "discard",
+ (PyCFunction)xu_buffer_discard,
+ METH_VARARGS,
+ "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
+
+ { "write",
+ (PyCFunction)xu_buffer_write,
+ METH_VARARGS,
+ "Write @string into buffer. Return number of bytes written.\n" },
+
+ { "empty",
+ (PyCFunction)xu_buffer_empty,
+ METH_VARARGS,
+ "Return TRUE if the buffer is empty.\n" },
+
+ { "full",
+ (PyCFunction)xu_buffer_full,
+ METH_VARARGS,
+ "Return TRUE if the buffer is full.\n" },
+
+ { NULL, NULL, 0, NULL }
+};
+
+staticforward PyTypeObject xu_buffer_type;
+
+static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
+{
+ xu_buffer_object *xub;
+
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
+
+ xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
+
+ if ( (xub->buf = malloc(BUFSZ)) == NULL )
{
- /* Update private indexes. */
- pinfo->tx_resp_prod = c;
- pinfo->tx_req_cons = c;
- /* Queue responses and send a notification to the guest OS. */
- cif->tx_resp_prod = c;
- return 1;
+ PyObject_Del((PyObject *)xub);
+ return NULL;
}
- return 0;
+ xub->prod = xub->cons = 0;
+
+ return (PyObject *)xub;
+}
+
+static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
+{
+ return Py_FindMethod(xu_buffer_methods, obj, name);
+}
+
+static void xu_buffer_dealloc(PyObject *self)
+{
+ xu_buffer_object *xub = (xu_buffer_object *)self;
+ free(xub->buf);
+ PyObject_Del(self);
}
-static int process_evtchn_writes(portinfo_t *pinfo)
+static PyTypeObject xu_buffer_type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "buffer",
+ sizeof(xu_buffer_object),
+ 0,
+ xu_buffer_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ xu_buffer_getattr, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL /* tp_hash */
+};
+
+
+
+/*
+ * *********************** MODULE WRAPPER ***********************
+ */
+
+static void handle_child_death(int dummy)
{
- CONTROL_RING_IDX p, rx_resp_prod;
- control_if_t *cif = pinfo->interface;
- control_msg_t *cmsg;
- unsigned int bytes;
+ while ( waitpid(-1, NULL, WNOHANG) > 0 )
+ continue;
+}
- /* Validate the rx-response producer, an dupdate our consumer if okay. */
- rx_resp_prod = cif->rx_resp_prod;
- if ( (pinfo->rx_resp_cons != rx_resp_prod) &&
- ((pinfo->rx_req_prod - rx_resp_prod) <= CONTROL_RING_SIZE) &&
- ((rx_resp_prod - pinfo->rx_resp_cons) <= CONTROL_RING_SIZE) )
- pinfo->rx_resp_cons = cif->rx_resp_prod;
+static PyObject *xu_autoreap(PyObject *self, PyObject *args)
+{
+ struct sigaction sa;
- for ( p = pinfo->rx_req_prod;
- (p-pinfo->rx_resp_cons) != CONTROL_RING_SIZE;
- p++ )
- {
- if ( TX_EMPTY(pinfo) )
- break;
- cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
- bytes = sizeof(cmsg->msg);
- /* Clip transfer to ring-buffer wrap. */
- if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc)) )
- bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc);
- /* Clip transfer to ring-buffer overflow. */
- if ( bytes > (pinfo->txp - pinfo->txc) )
- bytes = pinfo->txp - pinfo->txc;
- cmsg->cmd_type = CMD_CONSOLE;
- cmsg->cmd_subtype = CMD_CONSOLE_DATA;
- cmsg->id = 0xaa;
- cmsg->length = bytes;
- memcpy(&cmsg->msg[0],
- &pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txc)],
- bytes);
- pinfo->txc += bytes;
- }
+ if ( !PyArg_ParseTuple(args, "") )
+ return NULL;
- if ( p != pinfo->rx_req_prod )
- {
- pinfo->rx_req_prod = p;
- cif->rx_req_prod = p;
- return 1;
- }
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handle_child_death;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ (void)sigaction(SIGCHLD, &sa, NULL);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef xu_methods[] = {
+ { "notifier", xu_notifier_new, METH_VARARGS,
+ "Create a new notifier." },
+ { "message", xu_message_new, METH_VARARGS,
+ "Create a new communications message." },
+ { "port", xu_port_new, METH_VARARGS,
+ "Create a new communications port." },
+ { "buffer", xu_buffer_new, METH_VARARGS,
+ "Create a new ring buffer." },
+ { "autoreap", xu_autoreap, METH_VARARGS,
+ "Ensure that zombie children are automatically reaped by the OS." },
+ { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC initxend_utils(void)
+{
+ PyObject *m, *d;
+
+ m = Py_InitModule("xend_utils", xu_methods);
- return 0;
+ d = PyModule_GetDict(m);
+ port_error = PyErr_NewException("xend_utils.PortError", NULL, NULL);
+ PyDict_SetItemString(d, "PortError", port_error);
}
all: $(BIN)
install: all
- mkdir -p /usr/bin
- cp $(BIN) /usr/bin
- for i in $(BIN); do chmod 755 /usr/bin/$$i; done
- for i in $(MAN1); do cp $$i /usr/man/man1/$$i; done
- for i in $(MAN8); do cp $$i /usr/man/man8/$$i; done
+ mkdir -p $(prefix)/usr/bin
+ mkdir -p $(prefix)/usr/man/man1
+ mkdir -p $(prefix)/usr/man/man8
+ cp $(BIN) $(prefix)/usr/bin
+ for i in $(BIN); do chmod 755 $(prefix)/usr/bin/$$i; done
+ for i in $(MAN1); do cp $$i $(prefix)/usr/man/man1/$$i; done
+ for i in $(MAN8); do cp $$i $(prefix)/usr/man/man8/$$i; done
dist: all
mkdir -p ../../../install/bin
+ mkdir -p ../../../install/man/man1
+ mkdir -p ../../../install/man/man8
cp $(BIN) ../../../install/bin
- chmod 755 ../../../install/bin/$(BIN)
- cp $(SCRIPTS) ../../../install/bin
- for i in $(SCRIPTS); do chmod 755 ../../../install/bin/$i; done
+ for i in $(BIN); do chmod 755 ../../../install/bin/$$i; done
+ for i in $(MAN1); do cp $$i ../../../install/man/man1/$$i; done
+ for i in $(MAN8); do cp $$i ../../../install/man/man8/$$i; done
clean:
$(RM) *.a *.so *.o *.rpm $(BIN)
p = MASK_CONTROL_IDX(ctrl_if->tx_req_prod);
- ctrl_if->tx_ring[p].cmd_type = CMD_CONSOLE;
- ctrl_if->tx_ring[p].cmd_subtype = CMD_CONSOLE_DATA;
- ctrl_if->tx_ring[p].id = 0xaa;
+ ctrl_if->tx_ring[p].type = CMSG_CONSOLE;
+ ctrl_if->tx_ring[p].subtype = CMSG_CONSOLE_DATA;
+ ctrl_if->tx_ring[p].id = 0xaa;
src = dst = 0;
while ( (src < count) && (dst < (sizeof(ctrl_if->tx_ring[p].msg)-1)) )
{
for ( c = ctrl_if->rx_resp_prod; c != ctrl_if->rx_req_prod; c++ )
{
msg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(c)];
- if ( (msg->cmd_type == CMD_CONSOLE) &&
- (msg->cmd_subtype == CMD_CONSOLE_DATA) )
+ if ( (msg->type == CMSG_CONSOLE) &&
+ (msg->subtype == CMSG_CONSOLE_DATA) )
{
for ( i = 0; i < msg->length; i++ )
tty_insert_flip_char(xeno_console_tty, msg->msg[i], 0);
if ( (wc == wp) && (x_char == 0) )
break;
msg = &ctrl_if->tx_ring[MASK_CONTROL_IDX(c)];
- msg->cmd_type = CMD_CONSOLE;
- msg->cmd_subtype = CMD_CONSOLE_DATA;
- msg->id = 0xaa;
+ msg->type = CMSG_CONSOLE;
+ msg->subtype = CMSG_CONSOLE_DATA;
+ msg->id = 0xaa;
len = 0;
if ( x_char != 0 ) /* Handle XON/XOFF urgently. */
{
#define __CONTROL_IF_H__
typedef struct {
- u8 cmd_type; /* echoed in response */
- u8 cmd_subtype; /* echoed in response */
- u8 id; /* echoed in response */
- u8 length; /* number of bytes in 'msg' */
- unsigned char msg[60]; /* command-specific message data */
+ u8 type; /* echoed in response */
+ u8 subtype; /* echoed in response */
+ u8 id; /* echoed in response */
+ u8 length; /* number of bytes in 'msg' */
+ unsigned char msg[60]; /* type-specific message data */
} control_msg_t;
#define CONTROL_RING_SIZE 8
CONTROL_RING_IDX rx_req_prod, rx_resp_prod;
} control_if_t;
-#define CMD_CONSOLE 0
-#define CMD_CONSOLE_DATA 0
+#define CMSG_CONSOLE 0
+#define CMSG_CONSOLE_DATA 0
#endif /* __CONTROL_IF_H__ */